1. Opérateurs

Opérateurs

Ok, on a des variables mais on en fait quoi ?

Eh bien on peut faire des opérations avec !

Opérateurs arithmétiques

Les opérateurs arithmétiques sont utiles dans les calculs avec différents types de valeurs.

int a = 7;
int b = 3;

int c = a + b;
// ici, la variable c vaut 10, je suis ingénieur

Opérateurs binaires

On a accès à des opérations de base comme :

  • l'addition +
  • la soustraction -
  • la multiplication *
  • la division /
  • le modulo %

Modu-quoi ?

Le modulo c'est le résultat du reste de la division euclidienne. Ça n'a pas l'air très utile dit comme ça mais on trouve toujours des façon intéressantes de s'en servir, croyez moi !

Par exemple, 14 % 3 vaut 2 car 14 = 4 × 3 + 2.

Tout ces opérateurs sont bien classiques et je pense que vous voyez déjà comment on peut les utiliser. Ce sont des opérateurs binaires car ils prennent 2 opérandes pour calculer une valeur.

Ce ne sont pas les seuls opérateurs. Il en existe d'autres plus complexes :

  • les shifts <<, >>, >>>
  • les opérateurs arithmétiques logiques &, |, ^

On n'utilisera probablement pas ces opérateurs complexes, ou alors en guise d'exemple plus tard.
On les appelle des opérateurs bits-à-bits.

Cas spécial de la concaténation

L'opérateur + peut aussi servir pour combiner des variables de n'importe quel type avec des String ensemble !

void main() {
  int age = 37;
  String name = "Bob";
  
  println("Bonjour " + name + ". Tu as " + age + " ans !");
}

On appelle ça la concaténation de chaines de caractères et c'est très pratique !
(Il faut juste penser à mettre les espaces aux bons endroits)

Opérateurs unaires

Il existe aussi des opérateurs unaires :

  • l'incrémentation ++
  • la décrémentation --

Ce sont des opérateurs qui n'ont besoin que d'un opérande, et qui ajoutent et retirent respectivement 1 à la valeur.

int a = 4;

a++; // a vaut 5, son équivalent est a = a + 1
a--; // a vaut de nouveau 4, son équivalent est a = a - 1
  • l'opérateur négatif - (pour indiquer une valeur négative)
  • l'opérateur négatif + (il est optionnel, pour indiquer une valeur positive)
int a = -4;
int b = +7; // même chose que int b = 7;

a = -a; // a vaut 4

Opérateurs d'assignations

On trouve aussi les opérateurs d'assignation :

  • assignation =
  • assignation avec addition +=
  • assignation avec soustraction -=
  • assignation avec multiplication *=
  • assignation avec division /=
  • assignation avec modulo %=

Ce sont des raccourcis de notation pour une opération et une assignation en même temps :

int a = 1;

a += 3; // a vaut a + 3, donc a vaut 4

// est la même chose que

a = a + 3;

Opérateurs logiques

Les opérateurs logiques permettent de jouer avec des boolean. Ce sont eux qui permettent d'ajouter des la complexité dans nos programmes.

Il y a des opérateurs pour faire des comparaisons :

  • strictement supérieur >
  • strictement inférieur <
  • supérieur ou égal >=
  • inférieur ou égal <=
  • égalité ==
  • différence !=

Ces opérateurs renvoient un boolean pour savoir si c'est vrai ou faux.

1 < 2;  // true
1 > 2;  // false
2 >= 2; // true
3 == 4; //false
3 != 4; // true

Ou les opérateurs de combinaison logiques :

  • "et" &&
  • "ou" ||
  • "non" ! (opérateur unaire)

Ces opérateurs ne fonctionnent qu'avec des boolean et son utiles pour faire des calculs logiques plus complexes :

boolean resultat = true && false; // false

Il faut comprendre comment fonctionnent ces trois opérateurs car ils sont très important quand on veut ajouter de la complexité à nos programmes.

ET

L'opérateur && signifie un et logique. Pour qu'il renvoie true il faut que ses deux opérandes soient true. Sinon il renvoie false.

false && false; // false
false && true;  // false
true && false;  // false
true && true;   // true

OU

L'opérateur || signifie un ou logique. Pour qu'il renvoie true il faut que l'un ses deux opérandes soient true, ou les deux. Sinon il renvoie false.

false || false; // false
false || true;  // true
true || false;  // true
true || true;   // true

NON

L'opérateur ! signifie un non logique. Il renvoie l'inverse de son opérande :

!true;   // false
!false;  // true

Ternaire

Il existe un dernier opérateur logique un peu complexe : l'opérateur ternaire. Il permet de faire des choix avec 3 opérandes.

boolean ? valeur1 : valeur2;

Il évalue le boolean et si celui ci est vrai, il renvoie la valeur1 sinon il renvoie la valeur2

int a;

a = (3 < 4) ? 1 : 2; // a = 1
a = (3 > 4) ? 1 : 2; // a = 2

Note : les types de valeur1 et valeur2 doivent impérativement être le même que le type de a

Le cast

L'opérateur de cast est un opérateur unaire. (int) variable ​ (remplacez int par n'importe quel type)
Il permet de forcer Java à considérer une variable comme ayant le type indiqué entre les parenthèses. C'est un opérateur dangereux mais qui peut se révéler pratique.

int a = 5;
long b = (long) a; // b = 5L

Cet opérateur est à manipuler avec précaution car il va à l'encontre du système de typage qui permet normalement de s'assurer qu'on ne manipule pas les variables n'importe comment.

Il est parfois impératif dans le cas où vous faites des opérations sur des variables qui n'ont pas le même type :

int a = 5;
long b = 6;

int c1 = a + b; // ça ne fonctionne pas !
int c2 = (int) (a + b); // ça fonctionne !

Ici, je tente de calculer la somme d'un int et d'un long. En général, quand ce genre de choses arrive, Java va choisir le type le plus grand, ici c'est long. Or, un long est capable d'avoir des valeurs bien plus importantes qu'un int. Et la machine ne sait pas si cette somme ne dépassera pas la valeur maximale que peut stocker l'int. Donc dans le doute elle ne permet pas cette opération.
En revanche, nous en tant que professionnels, on sait que 5 + 6 sont loin de dépasser 2147483647 (la valeur max d'un int) donc on peut forcer l'opération en rajoutant un cast sur la somme. En faisant ça on dit à l'ordinateur "chuut ça va aller, tout doux, je sais ce que je fais, baisse tes boucliers". Il y a des cas où c'est pratique, mais si par malheur vous ne savez pas ce que vous faites et que vous l'utilisez quand même, je ne me porte pas responsable de ce qu'il va se passer dans votre programme ! Toutes sortes de comportements étranges pourraient avoir lieus, le plus sympa étant que votre programme plante immédiatement !

Les priorités opératoires

Les opérateurs ont tous une priorité. Par exemple, la multiplication a la priorité sur l'addition :2 + 3 * 4. C'est la même chose que 2 + (3 * 4).
On peut ajouter des parenthèses en cas de doutes ou de problèmes, mais il faut éviter de rendre la lecture trop pénible à force d'en rajouter. En général on préfère en mettre juste assez pour faciliter la compréhension en cas d'ambiguité.

La liste des priorités opératoires dans l'ordre de la plus grande à la plus petite

  • expr++, expr-- (incrémentation/décrémentation) (*)
  • ~, ++expr ​, --expr ​, +expr ​, -expr ​ (*), !expr ​ (*)
  • *, /, % (multiplications) (*)
  • +, - (additions) (*)
  • <<, >>, >>> (les shifts)
  • <, >, <=, >=, instanceof (comparaison) (*)
  • ==, != (égalité) (*)
  • & ("et" arithmétique logique)
  • ^ ("xor" arithmétique logique)
  • | ("ou" arithmétique logique)
  • && ("et" logique) (*)
  • || ("ou" logique) (*)
  • ? : (opérateur ternaire) (*)

J'ai noté d'une (*) ceux qui seront utilisés. Les autres sont trop complexes et peu utiles pour 99% de la population. Si vous êtes tout de même curieux je vous invite à vous renseigner sur les calculs bits-à-bits.

Gardez en tête que je n'ai pas parlé de instanceof car ils nous manque des notions pour le comprendre. Il reviendra plus tard mais ce n'est pas important.

Exercice

Je vais vous mettre un enchainement de code, essayez de trouver la valeur de a, b, c, d et e à la fin du programme ;

void main() {
  int a = 1;
  int b = 2;
  boolean c;
  boolean d;
  boolean e;

  a -= b;
  b *= 2;
  c = a >= 1;

  d = a == b && !c || a < b;

  e = d || !d;
  b *= a;
  a = b < 0 ? 10 : -10;
}

Solution

Alors, vous avez tout suivi ?

void main() {

  int a = 1;
  int b = 2;
  boolean c; // false
  boolean d; // false
  boolean e; // false

  a -= b; // a = a - b = (-1)
  b *= 2; // b = b * 2 = 4
  c = a >= 1; // -1 < 1 donc c = false

  /*
      je rajoute des parenthèses si la priorité n'était pas claire
      d = ((a == b) && (!c)) || (a < b);
  */
  d = a == b && !c || a < b; // false && true || true donc d = true

  e = d || !d; // e = true
  b *= a; // b = 4 * (-1) = (-4)
  a = b < 0 ? 10 : -10; // a = 10
}

À la fin on a donc :

a = 10;
b = -4;
c = false;
d = true;
e = true;

Bon, il est temps de découvrir ce qu'on fait de ces variables avec leurs opérateurs. Elles représentent des expressions parfaites pour utiliser avec les bonnes instructions de programmation.